//
// Maths.cpp for  in /home/goldbe_y//cpp/Maths/209ajust
//
// Made by yoni goldberg
// Login   <goldbe_y@epitech.net>
//
// Started on  Sat Jun 11 17:14:06 2011 yoni goldberg
// Last update Wed Jun 22 17:31:59 2011 yoni goldberg
//

#include "Maths2.hpp"
#include "convert.hpp"

Maths2::Maths2(std::vector<float> tab, std::vector<float> b) :
  x(tab),
  table(),
  Ox(b),
  Tx(),
  total(),
  moy(),
  prob()
{
  Moyenne();
  Probabilite();
  Calc();
  for (size_t i = 0 ; i < x.size(); ++i)
    {
      std::string temp = var_to_string(x[i], 0);
      table.push_back(temp);
    }
  regroup();
}

Maths2::~Maths2()
{

}

int	Maths2::readfile()
{
  std::ifstream	file("table");

  if (file.is_open())
    {
      size_t	j = 0;
      size_t	i = 0;
      std::string	line;
      std::vector< std::string >	tmp;
      while (std::getline(file, line, '\t'))
	{
	  std::string	tmp2;
	  size_t found = line.find_last_of("\n");
	  if (found != std::string::npos)
	    tmp2 = line.substr(0, found).c_str();
	  else
	    tmp2.assign(line);
	  tmp.push_back(tmp2);
	  i++;
	  if (i == 12)
	    {
	      j++;
	      i = 0;
	      if (j != 31) table_khi.push_back(tmp);
	      tmp.clear();
	    }
	}
      file.close();
    }
  else
    return (0);
  return (1);
}

double             Maths2::cnn(int nb1, int nb2)
{
  double   res = 1, div = 1;
  double	ret;

  for (int i = (nb1 <= (nb2 - nb1)) ? nb1 : (nb2 - nb1); i > 0; i--)
    {
      res *= (nb2--);
      div *= (i);
    }
  ret = (res/div);
  return (ret);
}

void		Maths2::Calc()
{
  float		count = 0;
  for (size_t i = 0; i < x.size() - 1; i++)
    {
      float	temp = total;
      temp *= cnn(i, total);
      temp *= pow(prob, i);
      temp *= pow((1 - prob), (total - i));
      count += temp;
      Tx.push_back(temp);
    }
  Tx.push_back(total - count);
  count = 0;
  for (size_t i = 0; i < x.size() - 1; i++)
    {
      float	temp = total;
      temp *= cnn(i, total);
      temp *= pow(prob2, i);
      temp *= pow((1 - prob2), (total - i));
      count += temp;
      Tx2.push_back(temp);
    }
  Tx2.push_back(total - count);
  count = 0;
  for (size_t i = 0; i < x.size() - 1; i++)
    {
      float	temp = total;
      temp *= cnn(i, total);
      temp *= pow(prob3, i);
      temp *= pow((1 - prob3), (total - i));
      count += temp;
      Tx3.push_back(temp);
    }
  Tx3.push_back(total - count);
}

void		Maths2::Probabilite()
{
  prob2 = (int)moy;
  prob3 = prob2 + 1;
  prob = moy/total;
  prob2 /= total;
  prob3 /= total;
}

void		Maths2::Moyenne()
{
  total = 0;
  moy = 0;
  for (size_t i = 0; i < Ox.size(); i++)
    {
      moy += (x[i] * Ox[i]);
      total += Ox[i];
    }
  moy /= total;
}

void		Maths2::regroup()
{
  while (find())
    for (size_t i = 0; i < Ox.size(); ++i)
      {
	if (Ox[i] < 5)
	  if (i < Ox.size() - 1)
	    {
	      Ox[i + 1] += Ox[i];
	      Tx[i + 1] += Tx[i];
	      Tx2[i + 1] += Tx2[i];
	      Tx3[i + 1] += Tx3[i];
	      std::string temp = table[i + 1];
	      table[i + 1] = table[i];
	      table[i + 1] += "-";
	      table[i + 1] += temp;
	      Ox.erase(Ox.begin() + i);
	      Tx.erase(Tx.begin() + i);
	      Tx2.erase(Tx2.begin() + i);
	      Tx3.erase(Tx3.begin() + i);
	      table.erase(table.begin() + i);
	      i = 0;
	    }
	  else
	    {
	      Ox[i - 1] += Ox[i];
	      Tx[i - 1] += Tx[i];
	      Tx2[i - 1] += Tx2[i];
	      Tx3[i - 1] += Tx3[i];
	      table[i - 1] += "-";
	      table[i - 1] += table[i];
	      Ox.erase(Ox.begin() + i);
	      Tx.erase(Tx.begin() + i);
	      Tx2.erase(Tx2.begin() + i);
	      Tx3.erase(Tx3.begin() + i);
	      table.erase(table.begin() + i);
	      i = 0;
	    }
      }
}
void		Maths2::regroup()
{
  while (find())
    for (size_t i = 0; i < Ox.size(); ++i)
      {
	if (Ox[i] < 5)
	  if (i < Ox.size() - 1)
	    {
	      Ox[i + 1] += Ox[i];
	      Tx[i + 1] += Tx[i];
	      Tx2[i + 1] += Tx2[i];
	      Tx3[i + 1] += Tx3[i];
	      std::string temp = table[i + 1];
	      table[i + 1] = table[i];
	      table[i + 1] += "-";
	      table[i + 1] += temp;
	      Ox.erase(Ox.begin() + i);
	      Tx.erase(Tx.begin() + i);
	      Tx2.erase(Tx2.begin() + i);
	      Tx3.erase(Tx3.begin() + i);
	      table.erase(table.begin() + i);
	      i = 0;
	    }
	  else
	    {
	      Ox[i - 1] += Ox[i];
	      Tx[i - 1] += Tx[i];
	      Tx2[i - 1] += Tx2[i];
	      Tx3[i - 1] += Tx3[i];
	      table[i - 1] += "-";
	      table[i - 1] += table[i];
	      Ox.erase(Ox.begin() + i);
	      Tx.erase(Tx.begin() + i);
	      Tx2.erase(Tx2.begin() + i);
	      Tx3.erase(Tx3.begin() + i);
	      table.erase(table.begin() + i);
	      i = 0;
	    }
      }
}

bool		Maths2::find()
{
  for (size_t i = 0; i < Ox.size(); ++i)
    if (Ox[i] < 5) return true;
  return false;
}

void		Maths2::Khi()
{
  khi = 0;
  for (size_t i = 0; i <  Ox.size() ; ++i)
    {
      float	temp = pow((Ox[i] - Tx[i]), 2);
      temp /= Tx[i];
      khi += temp;
    }
  for (size_t i = 0; i <  Ox.size() ; ++i)
    {
      float	temp = pow((Ox[i] - Tx2[i]), 2);
      temp /= Tx2[i];
      khi2 += temp;
    }
  for (size_t i = 0; i <  Ox.size() ; ++i)
    {
      float	temp = pow((Ox[i] - Tx3[i]), 2);
      temp /= Tx3[i];
      khi3 += temp;
    }

  size_t	i = 1;
  while (i < table_khi[Ox.size()-1].size()-1)
    {
      if (string_to_var<float>(table_khi[Ox.size()-1][i]) > khi2)
	break;
      i++;
    }

  res << "Resultat B(" << total << ";" << prob2 << ") : Compris entre : " table_khi[0][i] << "% et " << table_khi[0][i-1] << "%";

  size_t	i = 1;
  while (i < table_khi[Ox.size()-2].size()-1)
    {
      if (string_to_var<float>(table_khi[Ox.size()-2][i]) > khi)
	break;
      i++;
    }
  std::ostringstream res;
  res << "\nResultat B(" << total << ";" << prob << ") :  compris entre : " << table_khi[0][i]
      << "% et " << table_khi[0][i-1] << "%";

  size_t	i = 1;
  while (i < table_khi[Ox.size()-1].size()-1)
    {
      if (string_to_var<float>(table_khi[Ox.size()-1][i]) > khi3)
	break;
      i++;
    }
  res << "\n Resultat B(" << total << ";" << prob3 << ") : Compris entre : " table_khi[0][i] << "% et " << table_khi[0][i-1] << "%";
  return (res.str());
}
